{
 "metadata": {
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "mimetype": "text/x-python",
   "name": "python",
   "pygments_lexer": "ipython3"
  },
  "name": "",
  "signature": "sha256:e4dbef6fc65c1be6d0ab64906dc1ab7b1c910b8ce89388286c2992c2cb49f56a"
 },
 "nbformat": 3,
 "nbformat_minor": 0,
 "worksheets": [
  {
   "cells": [
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "Blending IPython's widgets and mpld3's plugins\n",
      "==============================================\n",
      "\n",
      "This notebook performs a function quite similar to the 'sliderPlugin' example.\n",
      "Browser side visualisation is actionable and triggers recalculations in the ipython backend.\n",
      "While the sliderPlugin connects to the kernel, we use IPython's facilities : interact does the lifting for us.\n",
      "\n",
      "Because you need an IPython instance running, you cannot use it directly on nbviewer for example. _You have to download this notebook and run it in IPython yourself._ \n",
      "\n",
      "I used IPython 3.0.0-dev as of 2014/11/03. The widget interface does not seems so stable for now so you may have to tinker to get this working. If you experience problems I think that the examples we built on would be good material to get the whole thing working again.\n",
      "\n",
      "Objective\n",
      "---------\n",
      "\n",
      "We want to fit a curve in a cloud of points.\n",
      "The points are drag/drop-able by the user of the notebook and upon dropping the point, the fit is recalculated.\n",
      "\n",
      "The model can be pretty much any $R \\to R$ function, with any number of parameters.\n",
      "\n",
      "In what follows you will see it :\n",
      "- (partially) applied to an \"first order exponential response to an Heavyside function\" (for lack of better wording on my side);\n",
      "- applied to an arc-tangente.\n",
      "\n",
      "\n",
      "Architecture\n",
      "------------\n",
      "\n",
      "Here is how things are organized :\n",
      "0. code copyied from the ClickInfo/DragPoints examples on the mpld3 side will generate updates when the user drag and drop the circles;\n",
      "1. these updates are the new coordinates of a given point of the cloud;\n",
      "2. the update trigger the 'change' event on a text widget from IPython (code taken from the custom widget example);\n",
      "3. IPython cogs and wheels transmit the update back to the IPython server side;\n",
      "4. where we recalculate parameters, and redraw everything."
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "# imports widget side\n",
      "# see https://github.com/ipython/ipython/blob/2.x/examples/Interactive%20Widgets/Custom%20Widgets.ipynb\n",
      "# and https://github.com/ipython/ipython/blob/master/examples/Interactive%20Widgets/Custom%20Widget%20-%20Hello%20World.ipynb\n",
      "\n",
      "from __future__ import print_function # For py 2.7 compat\n",
      "\n",
      "from IPython.html import widgets # Widget definitions\n",
      "from IPython.display import display # Used to display widgets in the notebook\n",
      "from IPython.utils.traitlets import Unicode # Used to declare attributes of our widget\n",
      "from IPython.html.widgets import interact, interactive, fixed"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 1
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "# imports render side\n",
      "# see http://mpld3.github.io/examples/drag_points.html\n",
      "\n",
      "import numpy as np\n",
      "import matplotlib.pyplot as plt\n",
      "import matplotlib as mpl\n",
      "\n",
      "import mpld3\n",
      "from mpld3 import plugins, utils"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 2
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "# imports solve side\n",
      "# see http://stackoverflow.com/questions/8739227/how-to-solve-a-pair-of-nonlinear-equations-using-python\n",
      "\n",
      "from scipy.optimize import fsolve\n",
      "\n",
      "#def expchelon(a, b, x):\n",
      "#    return a * (1 - np.exp(-b * x))\n",
      "\n",
      "#def fun(p1, p2):\n",
      "#    x1, y1 = p1\n",
      "#    x2, y2 = p2\n",
      "#    def equations(p):\n",
      "#        a, b = p\n",
      "#        return (y1 - expchelon(a, b, x1), y2 - expchelon(a, b, x2))\n",
      "#    return equations\n",
      "\n",
      "#equations = fun((1,1), (2,4))\n",
      "#a, b =  fsolve(equations, (1, 1))\n",
      "\n",
      "#print((a, b), expchelon(a, b, 1), expchelon(a, b, 2))"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 3
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "# widget sync'd python side\n",
      "class GraphWidget(widgets.DOMWidget):\n",
      "    _view_name = Unicode('GraphView', sync=True)\n",
      "    description = 'coord'    \n",
      "    value = Unicode(sync=True)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 4
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%%javascript\n",
      "//widget javascript side\n",
      "require([\"widgets/js/widget\", \"widgets/js/manager\"], function(widget, manager){\n",
      "    // is based on the DatePickerView\n",
      "    var GraphView = widget.DOMWidgetView.extend({\n",
      "        render: function() {\n",
      "            //@ attr id : this is the id we reach to in the dragended function in the DragPlugin\n",
      "            this.$text = $('<input />')\n",
      "                .attr('type', 'text')\n",
      "                .attr('id', 'feedback_widget')                \n",
      "                .appendTo(this.$el);\n",
      "        },\n",
      "        \n",
      "        update: function() {\n",
      "            this.$text.val(this.model.get('value'));\n",
      "            return GraphView.__super__.update.apply(this);\n",
      "        },\n",
      "        \n",
      "        events: {\"change\": \"handle_change\"},\n",
      "        \n",
      "        handle_change: function(event) {\n",
      "            this.model.set('value', this.$text.val());\n",
      "            this.touch();\n",
      "        },\n",
      "    });\n",
      "    \n",
      "    manager.WidgetManager.register_widget_view('GraphView', GraphView);\n",
      "});"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "javascript": [
        "//widget javascript side\n",
        "require([\"widgets/js/widget\", \"widgets/js/manager\"], function(widget, manager){\n",
        "    // is based on the DatePickerView\n",
        "    var GraphView = widget.DOMWidgetView.extend({\n",
        "        render: function() {\n",
        "            //@ attr id : this is the id we reach to in the dragended function in the DragPlugin\n",
        "            this.$text = $('<input />')\n",
        "                .attr('type', 'text')\n",
        "                .attr('id', 'feedback_widget')                \n",
        "                .appendTo(this.$el);\n",
        "        },\n",
        "        \n",
        "        update: function() {\n",
        "            this.$text.val(this.model.get('value'));\n",
        "            return GraphView.__super__.update.apply(this);\n",
        "        },\n",
        "        \n",
        "        events: {\"change\": \"handle_change\"},\n",
        "        \n",
        "        handle_change: function(event) {\n",
        "            this.model.set('value', this.$text.val());\n",
        "            this.touch();\n",
        "        },\n",
        "    });\n",
        "    \n",
        "    manager.WidgetManager.register_widget_view('GraphView', GraphView);\n",
        "});"
       ],
       "metadata": {},
       "output_type": "display_data",
       "text": [
        "<IPython.core.display.Javascript object>"
       ]
      }
     ],
     "prompt_number": 5
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "# visu plugin\n",
      "# based on DragPlugin\n",
      "class DragPlugin(plugins.PluginBase):\n",
      "    JAVASCRIPT = r\"\"\"\n",
      "$('#feedback_widget').hide();\n",
      "mpld3.register_plugin(\"drag\", DragPlugin);\n",
      "DragPlugin.prototype = Object.create(mpld3.Plugin.prototype);\n",
      "DragPlugin.prototype.constructor = DragPlugin;\n",
      "DragPlugin.prototype.requiredProps = [\"id\"];\n",
      "DragPlugin.prototype.defaultProps = {}\n",
      "function DragPlugin(fig, props){\n",
      "    mpld3.Plugin.call(this, fig, props);\n",
      "    mpld3.insert_css(\"#\" + fig.figid + \" path.dragging\",\n",
      "                     {\"fill-opacity\": \"1.0 !important\",\n",
      "                      \"stroke-opacity\": \"1.0 !important\"});\n",
      "};$\n",
      "\n",
      "DragPlugin.prototype.draw = function(){\n",
      "    var obj = mpld3.get_element(this.props.id);\n",
      "\n",
      "    var drag = d3.behavior.drag()\n",
      "        .origin(function(d) { return {x:obj.ax.x(d[0]),\n",
      "                                      y:obj.ax.y(d[1])}; })\n",
      "        .on(\"dragstart\", dragstarted)\n",
      "        .on(\"drag\", dragged)\n",
      "        .on(\"dragend\", dragended);\n",
      "\n",
      "    obj.elements()\n",
      "       .data(obj.offsets)\n",
      "       .style(\"cursor\", \"default\")\n",
      "       .call(drag);\n",
      "\n",
      "    function dragstarted(d) {\n",
      "      d3.event.sourceEvent.stopPropagation();\n",
      "      d3.select(this).classed(\"dragging\", true);\n",
      "    }\n",
      "\n",
      "    function dragged(d, i) {\n",
      "      d[0] = obj.ax.x.invert(d3.event.x);\n",
      "      d[1] = obj.ax.y.invert(d3.event.y);\n",
      "      d3.select(this)\n",
      "        .attr(\"transform\", \"translate(\" + [d3.event.x,d3.event.y] + \")\");\n",
      "    }\n",
      "\n",
      "    function dragended(d,i) {\n",
      "      d3.select(this).classed(\"dragging\", false);\n",
      "      // feed back the new position to python, triggering 'change' on the widget\n",
      "      $('#feedback_widget').val(\"\" + i + \",\" + d[0] + \",\" + d[1]).trigger(\"change\");\n",
      "    }\n",
      "}\"\"\"\n",
      "\n",
      "    def __init__(self, points):\n",
      "        if isinstance(points, mpl.lines.Line2D):\n",
      "            suffix = \"pts\"\n",
      "        else:\n",
      "            suffix = None\n",
      "\n",
      "        self.dict_ = {\"type\": \"drag\",\n",
      "                      \"id\": utils.get_id(points, suffix)}"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 6
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "# fit and draw\n",
      "class Fit(object):\n",
      "    def __init__(self, simulate, double_seeding=False):\n",
      "        self.simulate = simulate\n",
      "         \n",
      "        # i will draw initial points at random\n",
      "        # the number of points will increase until we match arity with the function to be fit(ted?)\n",
      "        pseudo_fit = []\n",
      "        while len(pseudo_fit) < 100:\n",
      "            # just in case, I want to avoid inifite loops...\n",
      "            try:\n",
      "                simulate(0, pseudo_fit)\n",
      "                print(\"we have %d parameters\"%len(pseudo_fit))\n",
      "                break\n",
      "            except IndexError:\n",
      "                pseudo_fit.append(1)\n",
      "                \n",
      "        # we generate a random cloud \n",
      "        # the dots are distributed in (>0, >0) quadrant    \n",
      "        self.p = np.random.standard_exponential((len(pseudo_fit), 2))\n",
      "        \n",
      "        # first guess ! all ones.\n",
      "        self.fit = np.array(pseudo_fit)\n",
      "                \n",
      "    def make_equations(self):\n",
      "        def equations(params):\n",
      "            return self.p[:,1] - self.simulate(self.p[:,0], params)\n",
      "        self.equations = equations\n",
      "    \n",
      "    def recalc_param(self):\n",
      "        self.make_equations()\n",
      "        self.fit = fsolve(self.equations, np.ones(self.fit.shape), xtol=0.01)\n",
      "        \n",
      "    def redraw(self, coord):\n",
      "        # we have an update !\n",
      "        \n",
      "        # record the new position for given point \n",
      "        if coord != \"\":\n",
      "            i, x, y = coord.split(\",\")\n",
      "            i = int(i)\n",
      "            self.p[i][0] = float(x)\n",
      "            self.p[i][1] = float(y)\n",
      "            \n",
      "        # recalculate best fit\n",
      "        self.recalc_param()\n",
      "        \n",
      "        # draw things\n",
      "        x = np.linspace(0, 10, 50) # 50 x points from 0 to 10\n",
      "        y = self.simulate(x, self.fit)\n",
      "    \n",
      "        fig, ax = plt.subplots()\n",
      "\n",
      "        points = ax.plot(self.p[:,0], self.p[:,1],'or', alpha=0.5, markersize=10, markeredgewidth=1)\n",
      "        \n",
      "        ax.plot(x,y,'r-')\n",
      "        ax.set_title(\"Click and Drag\\n, we match on : %s\"%np.array_str(self.fit, precision=2), fontsize=12)\n",
      "\n",
      "        plugins.connect(fig, DragPlugin(points[0]))\n",
      "\n",
      "        fig_h = mpld3.display()\n",
      "        display(fig_h)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 7
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "# click and drag not active here, we just show how we fit\n",
      "\n",
      "def exp_ech(x, params):\n",
      "    return params[0] * (1 - np.exp(-params[1] * x))\n",
      "\n",
      "# we ensure we will fit nicely by setting p[0] at [0,0]\n",
      "# in effect adding one degree of liberty\n",
      "Fit(exp_ech).redraw(\"0,0,0\")"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "we have 2 parameters\n"
       ]
      },
      {
       "html": [
        "\n",
        "\n",
        "<style>\n",
        "\n",
        "</style>\n",
        "\n",
        "<div id=\"fig_el3107140405297911456551053238\"></div>\n",
        "<script>\n",
        "function mpld3_load_lib(url, callback){\n",
        "  var s = document.createElement('script');\n",
        "  s.src = url;\n",
        "  s.async = true;\n",
        "  s.onreadystatechange = s.onload = callback;\n",
        "  s.onerror = function(){console.warn(\"failed to load library \" + url);};\n",
        "  document.getElementsByTagName(\"head\")[0].appendChild(s);\n",
        "}\n",
        "\n",
        "if(typeof(mpld3) !== \"undefined\" && mpld3._mpld3IsLoaded){\n",
        "   // already loaded: just create the figure\n",
        "   !function(mpld3){\n",
        "       \n",
        "$('#feedback_widget').hide();\n",
        "mpld3.register_plugin(\"drag\", DragPlugin);\n",
        "DragPlugin.prototype = Object.create(mpld3.Plugin.prototype);\n",
        "DragPlugin.prototype.constructor = DragPlugin;\n",
        "DragPlugin.prototype.requiredProps = [\"id\"];\n",
        "DragPlugin.prototype.defaultProps = {}\n",
        "function DragPlugin(fig, props){\n",
        "    mpld3.Plugin.call(this, fig, props);\n",
        "    mpld3.insert_css(\"#\" + fig.figid + \" path.dragging\",\n",
        "                     {\"fill-opacity\": \"1.0 !important\",\n",
        "                      \"stroke-opacity\": \"1.0 !important\"});\n",
        "};$\n",
        "\n",
        "DragPlugin.prototype.draw = function(){\n",
        "    var obj = mpld3.get_element(this.props.id);\n",
        "\n",
        "    var drag = d3.behavior.drag()\n",
        "        .origin(function(d) { return {x:obj.ax.x(d[0]),\n",
        "                                      y:obj.ax.y(d[1])}; })\n",
        "        .on(\"dragstart\", dragstarted)\n",
        "        .on(\"drag\", dragged)\n",
        "        .on(\"dragend\", dragended);\n",
        "\n",
        "    obj.elements()\n",
        "       .data(obj.offsets)\n",
        "       .style(\"cursor\", \"default\")\n",
        "       .call(drag);\n",
        "\n",
        "    function dragstarted(d) {\n",
        "      d3.event.sourceEvent.stopPropagation();\n",
        "      d3.select(this).classed(\"dragging\", true);\n",
        "    }\n",
        "\n",
        "    function dragged(d, i) {\n",
        "      d[0] = obj.ax.x.invert(d3.event.x);\n",
        "      d[1] = obj.ax.y.invert(d3.event.y);\n",
        "      d3.select(this)\n",
        "        .attr(\"transform\", \"translate(\" + [d3.event.x,d3.event.y] + \")\");\n",
        "    }\n",
        "\n",
        "    function dragended(d,i) {\n",
        "      d3.select(this).classed(\"dragging\", false);\n",
        "      // feed back the new position to python, triggering 'change' on the widget\n",
        "      $('#feedback_widget').val(\"\" + i + \",\" + d[0] + \",\" + d[1]).trigger(\"change\");\n",
        "    }\n",
        "}\n",
        "       mpld3.draw_figure(\"fig_el3107140405297911456551053238\", {\"id\": \"el3107140405297911456\", \"data\": {\"data02\": [[0.0, 0.0], [0.20408163265306123, 0.8401863265748215], [0.40816326530612246, 1.5252707331422624], [0.6122448979591837, 2.083885684703326], [0.8163265306122449, 2.539377973122316], [1.0204081632653061, 2.9107844745583766], [1.2244897959183674, 3.213627777982398], [1.4285714285714286, 3.460564937332482], [1.6326530612244898, 3.661916461300346], [1.836734693877551, 3.8260976493843324], [2.0408163265306123, 3.9599703014978136], [2.2448979591836737, 4.069129500508661], [2.4489795918367347, 4.158137453519027], [2.6530612244897958, 4.230714165064045], [2.857142857142857, 4.28989291123828], [3.0612244897959187, 4.33814701264631], [3.2653061224489797, 4.377493204534879], [3.4693877551020407, 4.409575924365084], [3.673469387755102, 4.435736039545188], [3.8775510204081636, 4.457066887735683], [4.081632653061225, 4.474459971878982], [4.285714285714286, 4.488642219734962], [4.4897959183673475, 4.500206365149963], [4.6938775510204085, 4.509635720816097], [4.8979591836734695, 4.517324377875275], [5.1020408163265305, 4.523593676591624], [5.3061224489795915, 4.528705636468659], [5.510204081632653, 4.5328739071105195], [5.714285714285714, 4.536272697508279], [5.918367346938775, 4.539044056942547], [6.122448979591837, 4.541303811800915], [6.326530612244898, 4.543146406433992], [6.530612244897959, 4.544648850369128], [6.73469387755102, 4.545873936851908], [6.938775510204081, 4.546872867231399], [7.142857142857143, 4.547687390872872], [7.346938775510204, 4.548351550033646], [7.551020408163265, 4.5488931026275585], [7.755102040816327, 4.549334682341118], [7.959183673469388, 4.549694744587368], [8.16326530612245, 4.549988337832698], [8.36734693877551, 4.550227732533475], [8.571428571428571, 4.550422933968361], [8.775510204081632, 4.550582100399603], [8.979591836734695, 4.550711884040021], [9.183673469387756, 4.550817709076048], [9.387755102040817, 4.550903998366545], [9.591836734693878, 4.5509743582920805], [9.795918367346939, 4.551031729480241], [10.0, 4.551078509706426]], \"data01\": [[0.0, 0.0], [0.11895260868630031, 0.5104271919327634]]}, \"axes\": [{\"sharex\": [], \"id\": \"el3107140405297913136\", \"ydomain\": [0.0, 5.0], \"paths\": [], \"axesbgalpha\": null, \"xlim\": [0.0, 10.0], \"yscale\": \"linear\", \"xscale\": \"linear\", \"texts\": [{\"id\": \"el3107140405297501968\", \"rotation\": -0.0, \"v_baseline\": \"auto\", \"fontsize\": 12.0, \"coordinates\": \"axes\", \"text\": \"Click and Drag\\n, we match on : [ 4.55  1.  ]\", \"position\": [0.5, 1.0144675925925926], \"zorder\": 3, \"alpha\": 1, \"color\": \"#000000\", \"h_anchor\": \"middle\"}], \"lines\": [{\"xindex\": 0, \"id\": \"el3107140405297638704\", \"data\": \"data02\", \"dasharray\": \"none\", \"linewidth\": 1.0, \"color\": \"#FF0000\", \"alpha\": 1, \"zorder\": 2, \"coordinates\": \"data\", \"yindex\": 1}], \"xdomain\": [0.0, 10.0], \"zoomable\": true, \"ylim\": [0.0, 5.0], \"markers\": [{\"xindex\": 0, \"id\": \"el3107140405297637920pts\", \"data\": \"data01\", \"facecolor\": \"#FF0000\", \"edgecolor\": \"#000000\", \"alpha\": 0.5, \"edgewidth\": 1, \"zorder\": 2, \"markerpath\": [[[0.0, 5.0], [1.3260155, 5.0], [2.597899353924267, 4.473168457941209], [3.5355339059327378, 3.5355339059327378], [4.473168457941209, 2.597899353924267], [5.0, 1.3260155], [5.0, 0.0], [5.0, -1.3260155], [4.473168457941209, -2.597899353924267], [3.5355339059327378, -3.5355339059327378], [2.597899353924267, -4.473168457941209], [1.3260155, -5.0], [0.0, -5.0], [-1.3260155, -5.0], [-2.597899353924267, -4.473168457941209], [-3.5355339059327378, -3.5355339059327378], [-4.473168457941209, -2.597899353924267], [-5.0, -1.3260155], [-5.0, 0.0], [-5.0, 1.3260155], [-4.473168457941209, 2.597899353924267], [-3.5355339059327378, 3.5355339059327378], [-2.597899353924267, 4.473168457941209], [-1.3260155, 5.0], [0.0, 5.0]], [\"M\", \"C\", \"C\", \"C\", \"C\", \"C\", \"C\", \"C\", \"C\", \"Z\"]], \"coordinates\": \"data\", \"yindex\": 1}], \"sharey\": [], \"images\": [], \"axesbg\": \"#FFFFFF\", \"bbox\": [0.125, 0.09999999999999998, 0.775, 0.8], \"collections\": [], \"axes\": [{\"nticks\": 6, \"scale\": \"linear\", \"position\": \"bottom\", \"tickvalues\": null, \"tickformat\": null, \"fontsize\": 12.0, \"grid\": {\"gridOn\": false}}, {\"nticks\": 6, \"scale\": \"linear\", \"position\": \"left\", \"tickvalues\": null, \"tickformat\": null, \"fontsize\": 12.0, \"grid\": {\"gridOn\": false}}]}], \"plugins\": [{\"type\": \"reset\"}, {\"button\": true, \"enabled\": false, \"type\": \"zoom\"}, {\"button\": true, \"enabled\": false, \"type\": \"boxzoom\"}, {\"id\": \"el3107140405297637920pts\", \"type\": \"drag\"}], \"height\": 480.0, \"width\": 640.0});\n",
        "   }(mpld3);\n",
        "}else if(typeof define === \"function\" && define.amd){\n",
        "   // require.js is available: use it to load d3/mpld3\n",
        "   require.config({paths: {d3: \"https://mpld3.github.io/js/d3.v3.min\"}});\n",
        "   require([\"d3\"], function(d3){\n",
        "      window.d3 = d3;\n",
        "      mpld3_load_lib(\"https://mpld3.github.io/js/mpld3.v0.3git.js\", function(){\n",
        "         \n",
        "$('#feedback_widget').hide();\n",
        "mpld3.register_plugin(\"drag\", DragPlugin);\n",
        "DragPlugin.prototype = Object.create(mpld3.Plugin.prototype);\n",
        "DragPlugin.prototype.constructor = DragPlugin;\n",
        "DragPlugin.prototype.requiredProps = [\"id\"];\n",
        "DragPlugin.prototype.defaultProps = {}\n",
        "function DragPlugin(fig, props){\n",
        "    mpld3.Plugin.call(this, fig, props);\n",
        "    mpld3.insert_css(\"#\" + fig.figid + \" path.dragging\",\n",
        "                     {\"fill-opacity\": \"1.0 !important\",\n",
        "                      \"stroke-opacity\": \"1.0 !important\"});\n",
        "};$\n",
        "\n",
        "DragPlugin.prototype.draw = function(){\n",
        "    var obj = mpld3.get_element(this.props.id);\n",
        "\n",
        "    var drag = d3.behavior.drag()\n",
        "        .origin(function(d) { return {x:obj.ax.x(d[0]),\n",
        "                                      y:obj.ax.y(d[1])}; })\n",
        "        .on(\"dragstart\", dragstarted)\n",
        "        .on(\"drag\", dragged)\n",
        "        .on(\"dragend\", dragended);\n",
        "\n",
        "    obj.elements()\n",
        "       .data(obj.offsets)\n",
        "       .style(\"cursor\", \"default\")\n",
        "       .call(drag);\n",
        "\n",
        "    function dragstarted(d) {\n",
        "      d3.event.sourceEvent.stopPropagation();\n",
        "      d3.select(this).classed(\"dragging\", true);\n",
        "    }\n",
        "\n",
        "    function dragged(d, i) {\n",
        "      d[0] = obj.ax.x.invert(d3.event.x);\n",
        "      d[1] = obj.ax.y.invert(d3.event.y);\n",
        "      d3.select(this)\n",
        "        .attr(\"transform\", \"translate(\" + [d3.event.x,d3.event.y] + \")\");\n",
        "    }\n",
        "\n",
        "    function dragended(d,i) {\n",
        "      d3.select(this).classed(\"dragging\", false);\n",
        "      // feed back the new position to python, triggering 'change' on the widget\n",
        "      $('#feedback_widget').val(\"\" + i + \",\" + d[0] + \",\" + d[1]).trigger(\"change\");\n",
        "    }\n",
        "}\n",
        "         mpld3.draw_figure(\"fig_el3107140405297911456551053238\", {\"id\": \"el3107140405297911456\", \"data\": {\"data02\": [[0.0, 0.0], [0.20408163265306123, 0.8401863265748215], [0.40816326530612246, 1.5252707331422624], [0.6122448979591837, 2.083885684703326], [0.8163265306122449, 2.539377973122316], [1.0204081632653061, 2.9107844745583766], [1.2244897959183674, 3.213627777982398], [1.4285714285714286, 3.460564937332482], [1.6326530612244898, 3.661916461300346], [1.836734693877551, 3.8260976493843324], [2.0408163265306123, 3.9599703014978136], [2.2448979591836737, 4.069129500508661], [2.4489795918367347, 4.158137453519027], [2.6530612244897958, 4.230714165064045], [2.857142857142857, 4.28989291123828], [3.0612244897959187, 4.33814701264631], [3.2653061224489797, 4.377493204534879], [3.4693877551020407, 4.409575924365084], [3.673469387755102, 4.435736039545188], [3.8775510204081636, 4.457066887735683], [4.081632653061225, 4.474459971878982], [4.285714285714286, 4.488642219734962], [4.4897959183673475, 4.500206365149963], [4.6938775510204085, 4.509635720816097], [4.8979591836734695, 4.517324377875275], [5.1020408163265305, 4.523593676591624], [5.3061224489795915, 4.528705636468659], [5.510204081632653, 4.5328739071105195], [5.714285714285714, 4.536272697508279], [5.918367346938775, 4.539044056942547], [6.122448979591837, 4.541303811800915], [6.326530612244898, 4.543146406433992], [6.530612244897959, 4.544648850369128], [6.73469387755102, 4.545873936851908], [6.938775510204081, 4.546872867231399], [7.142857142857143, 4.547687390872872], [7.346938775510204, 4.548351550033646], [7.551020408163265, 4.5488931026275585], [7.755102040816327, 4.549334682341118], [7.959183673469388, 4.549694744587368], [8.16326530612245, 4.549988337832698], [8.36734693877551, 4.550227732533475], [8.571428571428571, 4.550422933968361], [8.775510204081632, 4.550582100399603], [8.979591836734695, 4.550711884040021], [9.183673469387756, 4.550817709076048], [9.387755102040817, 4.550903998366545], [9.591836734693878, 4.5509743582920805], [9.795918367346939, 4.551031729480241], [10.0, 4.551078509706426]], \"data01\": [[0.0, 0.0], [0.11895260868630031, 0.5104271919327634]]}, \"axes\": [{\"sharex\": [], \"id\": \"el3107140405297913136\", \"ydomain\": [0.0, 5.0], \"paths\": [], \"axesbgalpha\": null, \"xlim\": [0.0, 10.0], \"yscale\": \"linear\", \"xscale\": \"linear\", \"texts\": [{\"id\": \"el3107140405297501968\", \"rotation\": -0.0, \"v_baseline\": \"auto\", \"fontsize\": 12.0, \"coordinates\": \"axes\", \"text\": \"Click and Drag\\n, we match on : [ 4.55  1.  ]\", \"position\": [0.5, 1.0144675925925926], \"zorder\": 3, \"alpha\": 1, \"color\": \"#000000\", \"h_anchor\": \"middle\"}], \"lines\": [{\"xindex\": 0, \"id\": \"el3107140405297638704\", \"data\": \"data02\", \"dasharray\": \"none\", \"linewidth\": 1.0, \"color\": \"#FF0000\", \"alpha\": 1, \"zorder\": 2, \"coordinates\": \"data\", \"yindex\": 1}], \"xdomain\": [0.0, 10.0], \"zoomable\": true, \"ylim\": [0.0, 5.0], \"markers\": [{\"xindex\": 0, \"id\": \"el3107140405297637920pts\", \"data\": \"data01\", \"facecolor\": \"#FF0000\", \"edgecolor\": \"#000000\", \"alpha\": 0.5, \"edgewidth\": 1, \"zorder\": 2, \"markerpath\": [[[0.0, 5.0], [1.3260155, 5.0], [2.597899353924267, 4.473168457941209], [3.5355339059327378, 3.5355339059327378], [4.473168457941209, 2.597899353924267], [5.0, 1.3260155], [5.0, 0.0], [5.0, -1.3260155], [4.473168457941209, -2.597899353924267], [3.5355339059327378, -3.5355339059327378], [2.597899353924267, -4.473168457941209], [1.3260155, -5.0], [0.0, -5.0], [-1.3260155, -5.0], [-2.597899353924267, -4.473168457941209], [-3.5355339059327378, -3.5355339059327378], [-4.473168457941209, -2.597899353924267], [-5.0, -1.3260155], [-5.0, 0.0], [-5.0, 1.3260155], [-4.473168457941209, 2.597899353924267], [-3.5355339059327378, 3.5355339059327378], [-2.597899353924267, 4.473168457941209], [-1.3260155, 5.0], [0.0, 5.0]], [\"M\", \"C\", \"C\", \"C\", \"C\", \"C\", \"C\", \"C\", \"C\", \"Z\"]], \"coordinates\": \"data\", \"yindex\": 1}], \"sharey\": [], \"images\": [], \"axesbg\": \"#FFFFFF\", \"bbox\": [0.125, 0.09999999999999998, 0.775, 0.8], \"collections\": [], \"axes\": [{\"nticks\": 6, \"scale\": \"linear\", \"position\": \"bottom\", \"tickvalues\": null, \"tickformat\": null, \"fontsize\": 12.0, \"grid\": {\"gridOn\": false}}, {\"nticks\": 6, \"scale\": \"linear\", \"position\": \"left\", \"tickvalues\": null, \"tickformat\": null, \"fontsize\": 12.0, \"grid\": {\"gridOn\": false}}]}], \"plugins\": [{\"type\": \"reset\"}, {\"button\": true, \"enabled\": false, \"type\": \"zoom\"}, {\"button\": true, \"enabled\": false, \"type\": \"boxzoom\"}, {\"id\": \"el3107140405297637920pts\", \"type\": \"drag\"}], \"height\": 480.0, \"width\": 640.0});\n",
        "      });\n",
        "    });\n",
        "}else{\n",
        "    // require.js not available: dynamically load d3 & mpld3\n",
        "    mpld3_load_lib(\"https://mpld3.github.io/js/d3.v3.min.js\", function(){\n",
        "         mpld3_load_lib(\"https://mpld3.github.io/js/mpld3.v0.3git.js\", function(){\n",
        "                 \n",
        "$('#feedback_widget').hide();\n",
        "mpld3.register_plugin(\"drag\", DragPlugin);\n",
        "DragPlugin.prototype = Object.create(mpld3.Plugin.prototype);\n",
        "DragPlugin.prototype.constructor = DragPlugin;\n",
        "DragPlugin.prototype.requiredProps = [\"id\"];\n",
        "DragPlugin.prototype.defaultProps = {}\n",
        "function DragPlugin(fig, props){\n",
        "    mpld3.Plugin.call(this, fig, props);\n",
        "    mpld3.insert_css(\"#\" + fig.figid + \" path.dragging\",\n",
        "                     {\"fill-opacity\": \"1.0 !important\",\n",
        "                      \"stroke-opacity\": \"1.0 !important\"});\n",
        "};$\n",
        "\n",
        "DragPlugin.prototype.draw = function(){\n",
        "    var obj = mpld3.get_element(this.props.id);\n",
        "\n",
        "    var drag = d3.behavior.drag()\n",
        "        .origin(function(d) { return {x:obj.ax.x(d[0]),\n",
        "                                      y:obj.ax.y(d[1])}; })\n",
        "        .on(\"dragstart\", dragstarted)\n",
        "        .on(\"drag\", dragged)\n",
        "        .on(\"dragend\", dragended);\n",
        "\n",
        "    obj.elements()\n",
        "       .data(obj.offsets)\n",
        "       .style(\"cursor\", \"default\")\n",
        "       .call(drag);\n",
        "\n",
        "    function dragstarted(d) {\n",
        "      d3.event.sourceEvent.stopPropagation();\n",
        "      d3.select(this).classed(\"dragging\", true);\n",
        "    }\n",
        "\n",
        "    function dragged(d, i) {\n",
        "      d[0] = obj.ax.x.invert(d3.event.x);\n",
        "      d[1] = obj.ax.y.invert(d3.event.y);\n",
        "      d3.select(this)\n",
        "        .attr(\"transform\", \"translate(\" + [d3.event.x,d3.event.y] + \")\");\n",
        "    }\n",
        "\n",
        "    function dragended(d,i) {\n",
        "      d3.select(this).classed(\"dragging\", false);\n",
        "      // feed back the new position to python, triggering 'change' on the widget\n",
        "      $('#feedback_widget').val(\"\" + i + \",\" + d[0] + \",\" + d[1]).trigger(\"change\");\n",
        "    }\n",
        "}\n",
        "                 mpld3.draw_figure(\"fig_el3107140405297911456551053238\", {\"id\": \"el3107140405297911456\", \"data\": {\"data02\": [[0.0, 0.0], [0.20408163265306123, 0.8401863265748215], [0.40816326530612246, 1.5252707331422624], [0.6122448979591837, 2.083885684703326], [0.8163265306122449, 2.539377973122316], [1.0204081632653061, 2.9107844745583766], [1.2244897959183674, 3.213627777982398], [1.4285714285714286, 3.460564937332482], [1.6326530612244898, 3.661916461300346], [1.836734693877551, 3.8260976493843324], [2.0408163265306123, 3.9599703014978136], [2.2448979591836737, 4.069129500508661], [2.4489795918367347, 4.158137453519027], [2.6530612244897958, 4.230714165064045], [2.857142857142857, 4.28989291123828], [3.0612244897959187, 4.33814701264631], [3.2653061224489797, 4.377493204534879], [3.4693877551020407, 4.409575924365084], [3.673469387755102, 4.435736039545188], [3.8775510204081636, 4.457066887735683], [4.081632653061225, 4.474459971878982], [4.285714285714286, 4.488642219734962], [4.4897959183673475, 4.500206365149963], [4.6938775510204085, 4.509635720816097], [4.8979591836734695, 4.517324377875275], [5.1020408163265305, 4.523593676591624], [5.3061224489795915, 4.528705636468659], [5.510204081632653, 4.5328739071105195], [5.714285714285714, 4.536272697508279], [5.918367346938775, 4.539044056942547], [6.122448979591837, 4.541303811800915], [6.326530612244898, 4.543146406433992], [6.530612244897959, 4.544648850369128], [6.73469387755102, 4.545873936851908], [6.938775510204081, 4.546872867231399], [7.142857142857143, 4.547687390872872], [7.346938775510204, 4.548351550033646], [7.551020408163265, 4.5488931026275585], [7.755102040816327, 4.549334682341118], [7.959183673469388, 4.549694744587368], [8.16326530612245, 4.549988337832698], [8.36734693877551, 4.550227732533475], [8.571428571428571, 4.550422933968361], [8.775510204081632, 4.550582100399603], [8.979591836734695, 4.550711884040021], [9.183673469387756, 4.550817709076048], [9.387755102040817, 4.550903998366545], [9.591836734693878, 4.5509743582920805], [9.795918367346939, 4.551031729480241], [10.0, 4.551078509706426]], \"data01\": [[0.0, 0.0], [0.11895260868630031, 0.5104271919327634]]}, \"axes\": [{\"sharex\": [], \"id\": \"el3107140405297913136\", \"ydomain\": [0.0, 5.0], \"paths\": [], \"axesbgalpha\": null, \"xlim\": [0.0, 10.0], \"yscale\": \"linear\", \"xscale\": \"linear\", \"texts\": [{\"id\": \"el3107140405297501968\", \"rotation\": -0.0, \"v_baseline\": \"auto\", \"fontsize\": 12.0, \"coordinates\": \"axes\", \"text\": \"Click and Drag\\n, we match on : [ 4.55  1.  ]\", \"position\": [0.5, 1.0144675925925926], \"zorder\": 3, \"alpha\": 1, \"color\": \"#000000\", \"h_anchor\": \"middle\"}], \"lines\": [{\"xindex\": 0, \"id\": \"el3107140405297638704\", \"data\": \"data02\", \"dasharray\": \"none\", \"linewidth\": 1.0, \"color\": \"#FF0000\", \"alpha\": 1, \"zorder\": 2, \"coordinates\": \"data\", \"yindex\": 1}], \"xdomain\": [0.0, 10.0], \"zoomable\": true, \"ylim\": [0.0, 5.0], \"markers\": [{\"xindex\": 0, \"id\": \"el3107140405297637920pts\", \"data\": \"data01\", \"facecolor\": \"#FF0000\", \"edgecolor\": \"#000000\", \"alpha\": 0.5, \"edgewidth\": 1, \"zorder\": 2, \"markerpath\": [[[0.0, 5.0], [1.3260155, 5.0], [2.597899353924267, 4.473168457941209], [3.5355339059327378, 3.5355339059327378], [4.473168457941209, 2.597899353924267], [5.0, 1.3260155], [5.0, 0.0], [5.0, -1.3260155], [4.473168457941209, -2.597899353924267], [3.5355339059327378, -3.5355339059327378], [2.597899353924267, -4.473168457941209], [1.3260155, -5.0], [0.0, -5.0], [-1.3260155, -5.0], [-2.597899353924267, -4.473168457941209], [-3.5355339059327378, -3.5355339059327378], [-4.473168457941209, -2.597899353924267], [-5.0, -1.3260155], [-5.0, 0.0], [-5.0, 1.3260155], [-4.473168457941209, 2.597899353924267], [-3.5355339059327378, 3.5355339059327378], [-2.597899353924267, 4.473168457941209], [-1.3260155, 5.0], [0.0, 5.0]], [\"M\", \"C\", \"C\", \"C\", \"C\", \"C\", \"C\", \"C\", \"C\", \"Z\"]], \"coordinates\": \"data\", \"yindex\": 1}], \"sharey\": [], \"images\": [], \"axesbg\": \"#FFFFFF\", \"bbox\": [0.125, 0.09999999999999998, 0.775, 0.8], \"collections\": [], \"axes\": [{\"nticks\": 6, \"scale\": \"linear\", \"position\": \"bottom\", \"tickvalues\": null, \"tickformat\": null, \"fontsize\": 12.0, \"grid\": {\"gridOn\": false}}, {\"nticks\": 6, \"scale\": \"linear\", \"position\": \"left\", \"tickvalues\": null, \"tickformat\": null, \"fontsize\": 12.0, \"grid\": {\"gridOn\": false}}]}], \"plugins\": [{\"type\": \"reset\"}, {\"button\": true, \"enabled\": false, \"type\": \"zoom\"}, {\"button\": true, \"enabled\": false, \"type\": \"boxzoom\"}, {\"id\": \"el3107140405297637920pts\", \"type\": \"drag\"}], \"height\": 480.0, \"width\": 640.0});\n",
        "            })\n",
        "         });\n",
        "}\n",
        "</script>"
       ],
       "metadata": {},
       "output_type": "display_data",
       "text": [
        "<IPython.core.display.HTML object>"
       ]
      }
     ],
     "prompt_number": 8
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "def arctan(x, params):\n",
      "    return params[0] * np.arctan(params[1] * x + params[2])\n",
      "\n",
      "my_fit = Fit(arctan)\n",
      "\n",
      "# not sure why, but you can't do\n",
      "# interact(my_fit.redraw, coord=GraphWidget())\n",
      "# so we need :\n",
      "def f(coord):\n",
      "    return my_fit.redraw(coord)\n",
      "    \n",
      "interact(f, coord=GraphWidget())"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "html": [
        "\n",
        "\n",
        "<style>\n",
        "\n",
        "</style>\n",
        "\n",
        "<div id=\"fig_el31071404053596221282692337935\"></div>\n",
        "<script>\n",
        "function mpld3_load_lib(url, callback){\n",
        "  var s = document.createElement('script');\n",
        "  s.src = url;\n",
        "  s.async = true;\n",
        "  s.onreadystatechange = s.onload = callback;\n",
        "  s.onerror = function(){console.warn(\"failed to load library \" + url);};\n",
        "  document.getElementsByTagName(\"head\")[0].appendChild(s);\n",
        "}\n",
        "\n",
        "if(typeof(mpld3) !== \"undefined\" && mpld3._mpld3IsLoaded){\n",
        "   // already loaded: just create the figure\n",
        "   !function(mpld3){\n",
        "       \n",
        "$('#feedback_widget').hide();\n",
        "mpld3.register_plugin(\"drag\", DragPlugin);\n",
        "DragPlugin.prototype = Object.create(mpld3.Plugin.prototype);\n",
        "DragPlugin.prototype.constructor = DragPlugin;\n",
        "DragPlugin.prototype.requiredProps = [\"id\"];\n",
        "DragPlugin.prototype.defaultProps = {}\n",
        "function DragPlugin(fig, props){\n",
        "    mpld3.Plugin.call(this, fig, props);\n",
        "    mpld3.insert_css(\"#\" + fig.figid + \" path.dragging\",\n",
        "                     {\"fill-opacity\": \"1.0 !important\",\n",
        "                      \"stroke-opacity\": \"1.0 !important\"});\n",
        "};$\n",
        "\n",
        "DragPlugin.prototype.draw = function(){\n",
        "    var obj = mpld3.get_element(this.props.id);\n",
        "\n",
        "    var drag = d3.behavior.drag()\n",
        "        .origin(function(d) { return {x:obj.ax.x(d[0]),\n",
        "                                      y:obj.ax.y(d[1])}; })\n",
        "        .on(\"dragstart\", dragstarted)\n",
        "        .on(\"drag\", dragged)\n",
        "        .on(\"dragend\", dragended);\n",
        "\n",
        "    obj.elements()\n",
        "       .data(obj.offsets)\n",
        "       .style(\"cursor\", \"default\")\n",
        "       .call(drag);\n",
        "\n",
        "    function dragstarted(d) {\n",
        "      d3.event.sourceEvent.stopPropagation();\n",
        "      d3.select(this).classed(\"dragging\", true);\n",
        "    }\n",
        "\n",
        "    function dragged(d, i) {\n",
        "      d[0] = obj.ax.x.invert(d3.event.x);\n",
        "      d[1] = obj.ax.y.invert(d3.event.y);\n",
        "      d3.select(this)\n",
        "        .attr(\"transform\", \"translate(\" + [d3.event.x,d3.event.y] + \")\");\n",
        "    }\n",
        "\n",
        "    function dragended(d,i) {\n",
        "      d3.select(this).classed(\"dragging\", false);\n",
        "      // feed back the new position to python, triggering 'change' on the widget\n",
        "      $('#feedback_widget').val(\"\" + i + \",\" + d[0] + \",\" + d[1]).trigger(\"change\");\n",
        "    }\n",
        "}\n",
        "       mpld3.draw_figure(\"fig_el31071404053596221282692337935\", {\"id\": \"el3107140405359622128\", \"data\": {\"data02\": [[0.0, 0.22204961729218367], [0.20408163265306123, 0.32784615360252883], [0.40816326530612246, 0.42000820625009994], [0.6122448979591837, 0.4984898554893393], [0.8163265306122449, 0.5645962035132674], [1.0204081632653061, 0.6201310700365578], [1.2244897959183674, 0.6669025977688562], [1.4285714285714286, 0.7065089602534448], [1.6326530612244898, 0.7402809394124418], [1.836734693877551, 0.7692950463777655], [2.0408163265306123, 0.7944110423755585], [2.2448979591836737, 0.8163129890357314], [2.4489795918367347, 0.8355458903038044], [2.6530612244897958, 0.8525458201716062], [2.857142857142857, 0.8676637563522296], [3.0612244897959187, 0.8811840921929976], [3.2653061224489797, 0.8933389058084799], [3.4693877551020407, 0.9043189416119419], [3.673469387755102, 0.9142820785457977], [3.8775510204081636, 0.9233598870774636], [4.081632653061225, 0.9316627335313649], [4.285714285714286, 0.9392837776771475], [4.4897959183673475, 0.9463021236376791], [4.6938775510204085, 0.9527853197096253], [4.8979591836734695, 0.9587913546002934], [5.1020408163265305, 0.9643702617813408], [5.3061224489795915, 0.9695654169744112], [5.510204081632653, 0.9744145938344098], [5.714285714285714, 0.9789508279202233], [5.918367346938775, 0.9832031277448935], [6.122448979591837, 0.9871970631283172], [6.326530612244898, 0.9909552545397305], [6.530612244897959, 0.994497782103462], [6.73469387755102, 0.9978425290730295], [6.938775510204081, 1.0010054715768653], [7.142857142857143, 1.004000924096474], [7.346938775510204, 1.0068417482997396], [7.551020408163265, 1.0095395314020157], [7.755102040816327, 1.0121047390776656], [7.959183673469388, 1.0145468470280805], [8.16326530612245, 1.0168744545780022], [8.36734693877551, 1.0190953830810388], [8.571428571428571, 1.021216761437499], [8.775510204081632, 1.0232451006396395], [8.979591836734695, 1.025186358942946], [9.183673469387756, 1.0270459990028669], [9.387755102040817, 1.0288290381032772], [9.591836734693878, 1.030540092427013], [9.795918367346939, 1.0321834161730323], [10.0, 1.033762936203543]], \"data01\": [[0.12162555525224888, 0.28746834700400237], [1.2201913236648678, 0.6661145850434619], [0.9047338592713005, 0.590093764287146]]}, \"axes\": [{\"sharex\": [], \"id\": \"el3107140405297924696\", \"ydomain\": [0.2, 1.1], \"paths\": [], \"axesbgalpha\": null, \"xlim\": [0.0, 10.0], \"yscale\": \"linear\", \"xscale\": \"linear\", \"texts\": [{\"id\": \"el3107140405294082256\", \"rotation\": -0.0, \"v_baseline\": \"auto\", \"fontsize\": 12.0, \"coordinates\": \"axes\", \"text\": \"Click and Drag\\n, we match on : [ 0.71  0.86  0.32]\", \"position\": [0.5, 1.0144675925925926], \"zorder\": 3, \"alpha\": 1, \"color\": \"#000000\", \"h_anchor\": \"middle\"}], \"lines\": [{\"xindex\": 0, \"id\": \"el3107140405293707784\", \"data\": \"data02\", \"dasharray\": \"none\", \"linewidth\": 1.0, \"color\": \"#FF0000\", \"alpha\": 1, \"zorder\": 2, \"coordinates\": \"data\", \"yindex\": 1}], \"xdomain\": [0.0, 10.0], \"zoomable\": true, \"ylim\": [0.2, 1.1], \"markers\": [{\"xindex\": 0, \"id\": \"el3107140405293682416pts\", \"data\": \"data01\", \"facecolor\": \"#FF0000\", \"edgecolor\": \"#000000\", \"alpha\": 0.5, \"edgewidth\": 1, \"zorder\": 2, \"markerpath\": [[[0.0, 5.0], [1.3260155, 5.0], [2.597899353924267, 4.473168457941209], [3.5355339059327378, 3.5355339059327378], [4.473168457941209, 2.597899353924267], [5.0, 1.3260155], [5.0, 0.0], [5.0, -1.3260155], [4.473168457941209, -2.597899353924267], [3.5355339059327378, -3.5355339059327378], [2.597899353924267, -4.473168457941209], [1.3260155, -5.0], [0.0, -5.0], [-1.3260155, -5.0], [-2.597899353924267, -4.473168457941209], [-3.5355339059327378, -3.5355339059327378], [-4.473168457941209, -2.597899353924267], [-5.0, -1.3260155], [-5.0, 0.0], [-5.0, 1.3260155], [-4.473168457941209, 2.597899353924267], [-3.5355339059327378, 3.5355339059327378], [-2.597899353924267, 4.473168457941209], [-1.3260155, 5.0], [0.0, 5.0]], [\"M\", \"C\", \"C\", \"C\", \"C\", \"C\", \"C\", \"C\", \"C\", \"Z\"]], \"coordinates\": \"data\", \"yindex\": 1}], \"sharey\": [], \"images\": [], \"axesbg\": \"#FFFFFF\", \"bbox\": [0.125, 0.09999999999999998, 0.775, 0.8], \"collections\": [], \"axes\": [{\"nticks\": 6, \"scale\": \"linear\", \"position\": \"bottom\", \"tickvalues\": null, \"tickformat\": null, \"fontsize\": 12.0, \"grid\": {\"gridOn\": false}}, {\"nticks\": 6, \"scale\": \"linear\", \"position\": \"left\", \"tickvalues\": null, \"tickformat\": null, \"fontsize\": 12.0, \"grid\": {\"gridOn\": false}}]}], \"plugins\": [{\"type\": \"reset\"}, {\"button\": true, \"enabled\": false, \"type\": \"zoom\"}, {\"button\": true, \"enabled\": false, \"type\": \"boxzoom\"}, {\"id\": \"el3107140405293682416pts\", \"type\": \"drag\"}], \"height\": 480.0, \"width\": 640.0});\n",
        "   }(mpld3);\n",
        "}else if(typeof define === \"function\" && define.amd){\n",
        "   // require.js is available: use it to load d3/mpld3\n",
        "   require.config({paths: {d3: \"https://mpld3.github.io/js/d3.v3.min\"}});\n",
        "   require([\"d3\"], function(d3){\n",
        "      window.d3 = d3;\n",
        "      mpld3_load_lib(\"https://mpld3.github.io/js/mpld3.v0.3git.js\", function(){\n",
        "         \n",
        "$('#feedback_widget').hide();\n",
        "mpld3.register_plugin(\"drag\", DragPlugin);\n",
        "DragPlugin.prototype = Object.create(mpld3.Plugin.prototype);\n",
        "DragPlugin.prototype.constructor = DragPlugin;\n",
        "DragPlugin.prototype.requiredProps = [\"id\"];\n",
        "DragPlugin.prototype.defaultProps = {}\n",
        "function DragPlugin(fig, props){\n",
        "    mpld3.Plugin.call(this, fig, props);\n",
        "    mpld3.insert_css(\"#\" + fig.figid + \" path.dragging\",\n",
        "                     {\"fill-opacity\": \"1.0 !important\",\n",
        "                      \"stroke-opacity\": \"1.0 !important\"});\n",
        "};$\n",
        "\n",
        "DragPlugin.prototype.draw = function(){\n",
        "    var obj = mpld3.get_element(this.props.id);\n",
        "\n",
        "    var drag = d3.behavior.drag()\n",
        "        .origin(function(d) { return {x:obj.ax.x(d[0]),\n",
        "                                      y:obj.ax.y(d[1])}; })\n",
        "        .on(\"dragstart\", dragstarted)\n",
        "        .on(\"drag\", dragged)\n",
        "        .on(\"dragend\", dragended);\n",
        "\n",
        "    obj.elements()\n",
        "       .data(obj.offsets)\n",
        "       .style(\"cursor\", \"default\")\n",
        "       .call(drag);\n",
        "\n",
        "    function dragstarted(d) {\n",
        "      d3.event.sourceEvent.stopPropagation();\n",
        "      d3.select(this).classed(\"dragging\", true);\n",
        "    }\n",
        "\n",
        "    function dragged(d, i) {\n",
        "      d[0] = obj.ax.x.invert(d3.event.x);\n",
        "      d[1] = obj.ax.y.invert(d3.event.y);\n",
        "      d3.select(this)\n",
        "        .attr(\"transform\", \"translate(\" + [d3.event.x,d3.event.y] + \")\");\n",
        "    }\n",
        "\n",
        "    function dragended(d,i) {\n",
        "      d3.select(this).classed(\"dragging\", false);\n",
        "      // feed back the new position to python, triggering 'change' on the widget\n",
        "      $('#feedback_widget').val(\"\" + i + \",\" + d[0] + \",\" + d[1]).trigger(\"change\");\n",
        "    }\n",
        "}\n",
        "         mpld3.draw_figure(\"fig_el31071404053596221282692337935\", {\"id\": \"el3107140405359622128\", \"data\": {\"data02\": [[0.0, 0.22204961729218367], [0.20408163265306123, 0.32784615360252883], [0.40816326530612246, 0.42000820625009994], [0.6122448979591837, 0.4984898554893393], [0.8163265306122449, 0.5645962035132674], [1.0204081632653061, 0.6201310700365578], [1.2244897959183674, 0.6669025977688562], [1.4285714285714286, 0.7065089602534448], [1.6326530612244898, 0.7402809394124418], [1.836734693877551, 0.7692950463777655], [2.0408163265306123, 0.7944110423755585], [2.2448979591836737, 0.8163129890357314], [2.4489795918367347, 0.8355458903038044], [2.6530612244897958, 0.8525458201716062], [2.857142857142857, 0.8676637563522296], [3.0612244897959187, 0.8811840921929976], [3.2653061224489797, 0.8933389058084799], [3.4693877551020407, 0.9043189416119419], [3.673469387755102, 0.9142820785457977], [3.8775510204081636, 0.9233598870774636], [4.081632653061225, 0.9316627335313649], [4.285714285714286, 0.9392837776771475], [4.4897959183673475, 0.9463021236376791], [4.6938775510204085, 0.9527853197096253], [4.8979591836734695, 0.9587913546002934], [5.1020408163265305, 0.9643702617813408], [5.3061224489795915, 0.9695654169744112], [5.510204081632653, 0.9744145938344098], [5.714285714285714, 0.9789508279202233], [5.918367346938775, 0.9832031277448935], [6.122448979591837, 0.9871970631283172], [6.326530612244898, 0.9909552545397305], [6.530612244897959, 0.994497782103462], [6.73469387755102, 0.9978425290730295], [6.938775510204081, 1.0010054715768653], [7.142857142857143, 1.004000924096474], [7.346938775510204, 1.0068417482997396], [7.551020408163265, 1.0095395314020157], [7.755102040816327, 1.0121047390776656], [7.959183673469388, 1.0145468470280805], [8.16326530612245, 1.0168744545780022], [8.36734693877551, 1.0190953830810388], [8.571428571428571, 1.021216761437499], [8.775510204081632, 1.0232451006396395], [8.979591836734695, 1.025186358942946], [9.183673469387756, 1.0270459990028669], [9.387755102040817, 1.0288290381032772], [9.591836734693878, 1.030540092427013], [9.795918367346939, 1.0321834161730323], [10.0, 1.033762936203543]], \"data01\": [[0.12162555525224888, 0.28746834700400237], [1.2201913236648678, 0.6661145850434619], [0.9047338592713005, 0.590093764287146]]}, \"axes\": [{\"sharex\": [], \"id\": \"el3107140405297924696\", \"ydomain\": [0.2, 1.1], \"paths\": [], \"axesbgalpha\": null, \"xlim\": [0.0, 10.0], \"yscale\": \"linear\", \"xscale\": \"linear\", \"texts\": [{\"id\": \"el3107140405294082256\", \"rotation\": -0.0, \"v_baseline\": \"auto\", \"fontsize\": 12.0, \"coordinates\": \"axes\", \"text\": \"Click and Drag\\n, we match on : [ 0.71  0.86  0.32]\", \"position\": [0.5, 1.0144675925925926], \"zorder\": 3, \"alpha\": 1, \"color\": \"#000000\", \"h_anchor\": \"middle\"}], \"lines\": [{\"xindex\": 0, \"id\": \"el3107140405293707784\", \"data\": \"data02\", \"dasharray\": \"none\", \"linewidth\": 1.0, \"color\": \"#FF0000\", \"alpha\": 1, \"zorder\": 2, \"coordinates\": \"data\", \"yindex\": 1}], \"xdomain\": [0.0, 10.0], \"zoomable\": true, \"ylim\": [0.2, 1.1], \"markers\": [{\"xindex\": 0, \"id\": \"el3107140405293682416pts\", \"data\": \"data01\", \"facecolor\": \"#FF0000\", \"edgecolor\": \"#000000\", \"alpha\": 0.5, \"edgewidth\": 1, \"zorder\": 2, \"markerpath\": [[[0.0, 5.0], [1.3260155, 5.0], [2.597899353924267, 4.473168457941209], [3.5355339059327378, 3.5355339059327378], [4.473168457941209, 2.597899353924267], [5.0, 1.3260155], [5.0, 0.0], [5.0, -1.3260155], [4.473168457941209, -2.597899353924267], [3.5355339059327378, -3.5355339059327378], [2.597899353924267, -4.473168457941209], [1.3260155, -5.0], [0.0, -5.0], [-1.3260155, -5.0], [-2.597899353924267, -4.473168457941209], [-3.5355339059327378, -3.5355339059327378], [-4.473168457941209, -2.597899353924267], [-5.0, -1.3260155], [-5.0, 0.0], [-5.0, 1.3260155], [-4.473168457941209, 2.597899353924267], [-3.5355339059327378, 3.5355339059327378], [-2.597899353924267, 4.473168457941209], [-1.3260155, 5.0], [0.0, 5.0]], [\"M\", \"C\", \"C\", \"C\", \"C\", \"C\", \"C\", \"C\", \"C\", \"Z\"]], \"coordinates\": \"data\", \"yindex\": 1}], \"sharey\": [], \"images\": [], \"axesbg\": \"#FFFFFF\", \"bbox\": [0.125, 0.09999999999999998, 0.775, 0.8], \"collections\": [], \"axes\": [{\"nticks\": 6, \"scale\": \"linear\", \"position\": \"bottom\", \"tickvalues\": null, \"tickformat\": null, \"fontsize\": 12.0, \"grid\": {\"gridOn\": false}}, {\"nticks\": 6, \"scale\": \"linear\", \"position\": \"left\", \"tickvalues\": null, \"tickformat\": null, \"fontsize\": 12.0, \"grid\": {\"gridOn\": false}}]}], \"plugins\": [{\"type\": \"reset\"}, {\"button\": true, \"enabled\": false, \"type\": \"zoom\"}, {\"button\": true, \"enabled\": false, \"type\": \"boxzoom\"}, {\"id\": \"el3107140405293682416pts\", \"type\": \"drag\"}], \"height\": 480.0, \"width\": 640.0});\n",
        "      });\n",
        "    });\n",
        "}else{\n",
        "    // require.js not available: dynamically load d3 & mpld3\n",
        "    mpld3_load_lib(\"https://mpld3.github.io/js/d3.v3.min.js\", function(){\n",
        "         mpld3_load_lib(\"https://mpld3.github.io/js/mpld3.v0.3git.js\", function(){\n",
        "                 \n",
        "$('#feedback_widget').hide();\n",
        "mpld3.register_plugin(\"drag\", DragPlugin);\n",
        "DragPlugin.prototype = Object.create(mpld3.Plugin.prototype);\n",
        "DragPlugin.prototype.constructor = DragPlugin;\n",
        "DragPlugin.prototype.requiredProps = [\"id\"];\n",
        "DragPlugin.prototype.defaultProps = {}\n",
        "function DragPlugin(fig, props){\n",
        "    mpld3.Plugin.call(this, fig, props);\n",
        "    mpld3.insert_css(\"#\" + fig.figid + \" path.dragging\",\n",
        "                     {\"fill-opacity\": \"1.0 !important\",\n",
        "                      \"stroke-opacity\": \"1.0 !important\"});\n",
        "};$\n",
        "\n",
        "DragPlugin.prototype.draw = function(){\n",
        "    var obj = mpld3.get_element(this.props.id);\n",
        "\n",
        "    var drag = d3.behavior.drag()\n",
        "        .origin(function(d) { return {x:obj.ax.x(d[0]),\n",
        "                                      y:obj.ax.y(d[1])}; })\n",
        "        .on(\"dragstart\", dragstarted)\n",
        "        .on(\"drag\", dragged)\n",
        "        .on(\"dragend\", dragended);\n",
        "\n",
        "    obj.elements()\n",
        "       .data(obj.offsets)\n",
        "       .style(\"cursor\", \"default\")\n",
        "       .call(drag);\n",
        "\n",
        "    function dragstarted(d) {\n",
        "      d3.event.sourceEvent.stopPropagation();\n",
        "      d3.select(this).classed(\"dragging\", true);\n",
        "    }\n",
        "\n",
        "    function dragged(d, i) {\n",
        "      d[0] = obj.ax.x.invert(d3.event.x);\n",
        "      d[1] = obj.ax.y.invert(d3.event.y);\n",
        "      d3.select(this)\n",
        "        .attr(\"transform\", \"translate(\" + [d3.event.x,d3.event.y] + \")\");\n",
        "    }\n",
        "\n",
        "    function dragended(d,i) {\n",
        "      d3.select(this).classed(\"dragging\", false);\n",
        "      // feed back the new position to python, triggering 'change' on the widget\n",
        "      $('#feedback_widget').val(\"\" + i + \",\" + d[0] + \",\" + d[1]).trigger(\"change\");\n",
        "    }\n",
        "}\n",
        "                 mpld3.draw_figure(\"fig_el31071404053596221282692337935\", {\"id\": \"el3107140405359622128\", \"data\": {\"data02\": [[0.0, 0.22204961729218367], [0.20408163265306123, 0.32784615360252883], [0.40816326530612246, 0.42000820625009994], [0.6122448979591837, 0.4984898554893393], [0.8163265306122449, 0.5645962035132674], [1.0204081632653061, 0.6201310700365578], [1.2244897959183674, 0.6669025977688562], [1.4285714285714286, 0.7065089602534448], [1.6326530612244898, 0.7402809394124418], [1.836734693877551, 0.7692950463777655], [2.0408163265306123, 0.7944110423755585], [2.2448979591836737, 0.8163129890357314], [2.4489795918367347, 0.8355458903038044], [2.6530612244897958, 0.8525458201716062], [2.857142857142857, 0.8676637563522296], [3.0612244897959187, 0.8811840921929976], [3.2653061224489797, 0.8933389058084799], [3.4693877551020407, 0.9043189416119419], [3.673469387755102, 0.9142820785457977], [3.8775510204081636, 0.9233598870774636], [4.081632653061225, 0.9316627335313649], [4.285714285714286, 0.9392837776771475], [4.4897959183673475, 0.9463021236376791], [4.6938775510204085, 0.9527853197096253], [4.8979591836734695, 0.9587913546002934], [5.1020408163265305, 0.9643702617813408], [5.3061224489795915, 0.9695654169744112], [5.510204081632653, 0.9744145938344098], [5.714285714285714, 0.9789508279202233], [5.918367346938775, 0.9832031277448935], [6.122448979591837, 0.9871970631283172], [6.326530612244898, 0.9909552545397305], [6.530612244897959, 0.994497782103462], [6.73469387755102, 0.9978425290730295], [6.938775510204081, 1.0010054715768653], [7.142857142857143, 1.004000924096474], [7.346938775510204, 1.0068417482997396], [7.551020408163265, 1.0095395314020157], [7.755102040816327, 1.0121047390776656], [7.959183673469388, 1.0145468470280805], [8.16326530612245, 1.0168744545780022], [8.36734693877551, 1.0190953830810388], [8.571428571428571, 1.021216761437499], [8.775510204081632, 1.0232451006396395], [8.979591836734695, 1.025186358942946], [9.183673469387756, 1.0270459990028669], [9.387755102040817, 1.0288290381032772], [9.591836734693878, 1.030540092427013], [9.795918367346939, 1.0321834161730323], [10.0, 1.033762936203543]], \"data01\": [[0.12162555525224888, 0.28746834700400237], [1.2201913236648678, 0.6661145850434619], [0.9047338592713005, 0.590093764287146]]}, \"axes\": [{\"sharex\": [], \"id\": \"el3107140405297924696\", \"ydomain\": [0.2, 1.1], \"paths\": [], \"axesbgalpha\": null, \"xlim\": [0.0, 10.0], \"yscale\": \"linear\", \"xscale\": \"linear\", \"texts\": [{\"id\": \"el3107140405294082256\", \"rotation\": -0.0, \"v_baseline\": \"auto\", \"fontsize\": 12.0, \"coordinates\": \"axes\", \"text\": \"Click and Drag\\n, we match on : [ 0.71  0.86  0.32]\", \"position\": [0.5, 1.0144675925925926], \"zorder\": 3, \"alpha\": 1, \"color\": \"#000000\", \"h_anchor\": \"middle\"}], \"lines\": [{\"xindex\": 0, \"id\": \"el3107140405293707784\", \"data\": \"data02\", \"dasharray\": \"none\", \"linewidth\": 1.0, \"color\": \"#FF0000\", \"alpha\": 1, \"zorder\": 2, \"coordinates\": \"data\", \"yindex\": 1}], \"xdomain\": [0.0, 10.0], \"zoomable\": true, \"ylim\": [0.2, 1.1], \"markers\": [{\"xindex\": 0, \"id\": \"el3107140405293682416pts\", \"data\": \"data01\", \"facecolor\": \"#FF0000\", \"edgecolor\": \"#000000\", \"alpha\": 0.5, \"edgewidth\": 1, \"zorder\": 2, \"markerpath\": [[[0.0, 5.0], [1.3260155, 5.0], [2.597899353924267, 4.473168457941209], [3.5355339059327378, 3.5355339059327378], [4.473168457941209, 2.597899353924267], [5.0, 1.3260155], [5.0, 0.0], [5.0, -1.3260155], [4.473168457941209, -2.597899353924267], [3.5355339059327378, -3.5355339059327378], [2.597899353924267, -4.473168457941209], [1.3260155, -5.0], [0.0, -5.0], [-1.3260155, -5.0], [-2.597899353924267, -4.473168457941209], [-3.5355339059327378, -3.5355339059327378], [-4.473168457941209, -2.597899353924267], [-5.0, -1.3260155], [-5.0, 0.0], [-5.0, 1.3260155], [-4.473168457941209, 2.597899353924267], [-3.5355339059327378, 3.5355339059327378], [-2.597899353924267, 4.473168457941209], [-1.3260155, 5.0], [0.0, 5.0]], [\"M\", \"C\", \"C\", \"C\", \"C\", \"C\", \"C\", \"C\", \"C\", \"Z\"]], \"coordinates\": \"data\", \"yindex\": 1}], \"sharey\": [], \"images\": [], \"axesbg\": \"#FFFFFF\", \"bbox\": [0.125, 0.09999999999999998, 0.775, 0.8], \"collections\": [], \"axes\": [{\"nticks\": 6, \"scale\": \"linear\", \"position\": \"bottom\", \"tickvalues\": null, \"tickformat\": null, \"fontsize\": 12.0, \"grid\": {\"gridOn\": false}}, {\"nticks\": 6, \"scale\": \"linear\", \"position\": \"left\", \"tickvalues\": null, \"tickformat\": null, \"fontsize\": 12.0, \"grid\": {\"gridOn\": false}}]}], \"plugins\": [{\"type\": \"reset\"}, {\"button\": true, \"enabled\": false, \"type\": \"zoom\"}, {\"button\": true, \"enabled\": false, \"type\": \"boxzoom\"}, {\"id\": \"el3107140405293682416pts\", \"type\": \"drag\"}], \"height\": 480.0, \"width\": 640.0});\n",
        "            })\n",
        "         });\n",
        "}\n",
        "</script>"
       ],
       "metadata": {},
       "output_type": "display_data",
       "text": [
        "<IPython.core.display.HTML object>"
       ]
      }
     ],
     "prompt_number": 9
    }
   ],
   "metadata": {}
  }
 ]
}